package com.link.base.ext.autocfg.service;

import com.link.base.user.model.CoreUser;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.model.BasicModel;
import com.link.core.basic.query.Filter;
import com.link.core.basic.query.QueryParams;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.KeyGenerateService;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.AppConstants;
import com.link.core.util.UserUtil;
import com.link.base.ext.autocfg.dao.mybatis.mapper.AutoCfgItemMapper;
import com.link.base.ext.autocfg.model.AutoCfg;
import com.link.base.ext.autocfg.model.AutoCfgItem;
import com.link.base.ext.autocfg.model.AutoCfgItemSub;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class AutoCfgItemServiceImpl extends BasicServiceImpl<AutoCfgItem> implements AutoCfgItemService {

    private static final Logger logger = LogManager.getLogger(AutoCfgItemServiceImpl.class);

    @Resource
    private AutoCfgItemMapper autoCfgItemMapper;
    @Resource
    private KeyGenerateService keyGenerateService;
    @Resource
    private AutoCfgService autoCfgService;
    @Resource
    private AutoCfgItemSubService autoCfgItemSubService;

    @Override
    public BasicMapper<AutoCfgItem> getBasicMapper() {
        return autoCfgItemMapper;
    }

    /**
     * 获取直接头对象下的配置行信息
     */
    @Override
    public List<AutoCfgItem> getExtConfig(AutoCfgItem example) throws Exception {

        example.setPageFlag(false);
        //String loginCorpId = example.getLoginCorpId();

        //查询客户化行
        List<AutoCfgItem> customList = null;
        if (!AppConstants.ADMIN_CORP_ID.equals(example.getLoginCorpId())) {
            customList = autoCfgItemMapper.queryByExamplePage(example);
        }

        //查询标准行
        example.setLoginCorpId(AppConstants.ADMIN_CORP_ID);
        example.setCorpid(AppConstants.ADMIN_CORP_ID);
        List<AutoCfgItem> standardList = autoCfgItemMapper.queryByExamplePage(example);

        //重置账套id
        //example.setLoginCorpId(loginCorpId);
        //example.setCorpid(loginCorpId);

        if (standardList == null) {
            standardList = new ArrayList<AutoCfgItem>();
        }

        //合并
        for (int i = 0; customList != null && i < customList.size(); i++) {
            AutoCfgItem customItem = customList.get(i);
            Long basicId = customItem.getBasicId();
            boolean flag = false;
            for (int j = 0; j < standardList.size(); j++) {
                if (basicId == null) {
                    break;
                }
                if (basicId.equals(standardList.get(j).getId())) {
                    flag = true;
                    standardList.set(j, customItem);
                    break;
                }
            }
            if (!flag) {
                standardList.add(customItem);
            }
        }
        //升序排序
        Collections.sort(standardList, new Comparator<AutoCfgItem>() {
            @Override
            public int compare(AutoCfgItem o1, AutoCfgItem o2) {
                if (o1.getSeq() == null) {
                    return -1;
                } else if (o2.getSeq() == null) {
                    return 1;
                } else if (o1.getSeq().equals(o2.getSeq())) {
                    return 0;
                }
                return o1.getSeq() > o2.getSeq() ? 1 : -1;
            }
        });
        return standardList;
    }

    /**
     * <p>获取直接头对象配置行信息，关联头对象的配置信息，并合并</p>
     *
     * @author yrf
     * @param example
     * @param qps
     * @throws Exception
     */
    public List<AutoCfgItem> getExtConfig(AutoCfgItem example, QueryParams qps, String ss) throws Exception {
        List<AutoCfgItem> list = getExtConfig(example);
        Long parentStandardBasicId;
        if (list != null && list.size() > 0) {
            parentStandardBasicId = list.get(0).getParentStandardBasicId();
        } else {
            parentStandardBasicId = example.getParentStandardBasicId();
            //标准父ID为空，查询父对象获取标准父id
            if (null == parentStandardBasicId && null != example.getHeadId()) {
                AutoCfg headExample = new AutoCfg();
                headExample.setId(example.getHeadId());
                headExample.setUnionStandardCorp(0L);
                AutoCfg head = autoCfgService.queryById(headExample);
                parentStandardBasicId = head != null ? head.getStandardBasicId() : null;
            }
        }

        //无关联对象，返回
        if (null == parentStandardBasicId) {
            return list;
        }

        //设置关联对象行查询条件
        example.setHeadId(parentStandardBasicId);
        if (qps != null) {
            List<Filter> filters = qps.getFilters();
            for (Filter filter : filters) {
                if ("headId".equalsIgnoreCase(filter.getProperty())) {
                    filter.setValue(parentStandardBasicId.toString());
                }
            }
            example = (AutoCfgItem) BasicModel.transformClass(example, qps);
            example.setLoginCorpId(AppConstants.ADMIN_CORP_ID);
            example.setCorpid(AppConstants.ADMIN_CORP_ID);
            example.setPageFlag(false);
        }

        //查询关联对象行
        List<AutoCfgItem> linkItemList = autoCfgItemMapper.queryByExamplePage(example);

        //合并直接对象行与关联对象行，对象指配置头
        for (AutoCfgItem linkItem : linkItemList) {
            Long linkItemId = linkItem.getId();
            boolean foundFlag = false;
            for (int i = 0; i < list.size(); i++) {
                if (linkItemId.equals(list.get(i).getBasicId())) {
                    foundFlag = true;
                    break;
                }
            }
            if (!foundFlag) {
                list.add(linkItem);
            }
        }

        //升序排序
        Collections.sort(list, new Comparator<AutoCfgItem>() {
            @Override
            public int compare(AutoCfgItem o1, AutoCfgItem o2) {
                if (o1.getSeq() == null) {
                    return -1;
                } else if (o2.getSeq() == null) {
                    return 1;
                } else if (o1.getSeq().equals(o2.getSeq())) {
                    return 0;
                }
                return o1.getSeq() > o2.getSeq() ? 1 : -1;
            }
        });

        return list;
    }

    @Override
    public List<AutoCfgItem> getExtConfig(AutoCfgItem example, QueryParams qps) throws Exception {

        Long filterHeadId = null;
        if (qps != null) {
            List<Filter> filters = qps.getFilters();
            //boolean foundFlag = false;
            for (int i = 0; filters != null && i < filters.size(); i++) {
                Filter filter = filters.get(i);
                if ("headId".equalsIgnoreCase(filter.getProperty())) {
                    if (Filter.OP_EQUAL.equals(filter.getOperator())) {
                        filterHeadId = Long.parseLong(filter.getValue());
                    }
                    filters.remove(i);
                    i--;
                    //break;
                }
            }
        }

        Long headId = example.getHeadId() == null ? filterHeadId : example.getHeadId();
        if (null == headId) {
            throw new ServiceException("AUTOCFG-005");
        }
        AutoCfg headExample = new AutoCfg();
        headExample.setId(headId);
        AutoCfg headRecord = autoCfgService.queryById(headExample);
        if (headRecord == null) {
            throw new ServiceException("AUTOCFG-006");
        }
        Long headBasicId = headRecord.getBasicId() == null ? headId : headRecord.getBasicId();
        example.setHeadId(headId);
        example.setParentStandardBasicId(headBasicId);
        if (qps != null) {
            example = (AutoCfgItem) BasicModel.transformClass(example, qps);
        }
        List<AutoCfgItem> list = autoCfgItemMapper.queryUnionByExamplePage(example);

        return list;
        //return null;
    }

    @Override
    public void update(AutoCfgItem record) throws Exception {
        CoreUser user = UserUtil.getUser();
        if (user == null) {
            throw new ServiceException("AUTOCFG-007");
        }
        Long corpId = record.getCorpid() == null ? 0L : record.getCorpid();
        if (corpId.equals(user.getCorpid())) {
            super.update(record);
        } else if (AppConstants.ADMIN_CORP_ID.equals(corpId)) {
            /**
             * 标准字段复制一份到该账套
             */
            record.setJoinSubFlag(true);
            record.setSelectOneFlag(false);
            AutoCfgItem basicRecord = autoCfgItemMapper.queryById(record);
            if (basicRecord == null) {
                throw new ServiceException("AUTOCFG-008");
            }
            AutoCfgItem temp = new AutoCfgItem();
            BeanUtils.copyProperties(basicRecord, temp);

            record.setStandardFieldFlag(basicRecord.getStandardFieldFlag());//是否标准字段
            record.setJoinFlag(basicRecord.getJoinFlag());//是否关联字段
            record.setExtFlag(basicRecord.getExtFlag());//是否扩展字段
            record.setReservedFieldFlag(basicRecord.getReservedFieldFlag());//是否预留字段
            record.setName(basicRecord.getName());//字段名称
            /** 标准字段 */
            if ("Y".equals(basicRecord.getStandardFieldFlag())) {
                record.setReadOnly(basicRecord.getReadOnly());//只读
                record.setRequired(basicRecord.getRequired());//必填
            }

            record.setBasicId(basicRecord.getId());//源id
            record.setId(keyGenerateService.keyGenerate());
            record.setCorpid(user.getCorpid());
            record.setAttr1("Y");
            insert(record);

            //配置行的扩展属性复制
            if (basicRecord.getSubList() != null && basicRecord.getSubList().size() > 0) {
                for (AutoCfgItemSub sub : basicRecord.getSubList()) {
                    sub.setParentId(record.getId());
                    sub.setBasicStandardId(sub.getId());
                    sub.setId(null);
                    autoCfgItemSubService.insert(sub);
                }
            }
        }
    }

    @Override
    public void beforInsert(AutoCfgItem record) throws Exception {
        CoreUser user = UserUtil.getUser();
        if (user == null) {
            throw new ServiceException("AUTOCFG-007");
        }
        Long corpId = user.getCorpid();

        if (!AppConstants.ADMIN_CORP_ID.equals(corpId) && !"Y".equals(record.getAttr1())) {
            record.setExtFlag("Y");
            record.setJoinFlag("N");
        }
    }

    @Override
    @Transactional(rollbackFor = BasicServiceException.class)
    public Map<String, Object> swapSeq(Long id1,
                                       Long id2,
                                       Long corp1,
                                       Long corp2,
                                       Long headId) throws Exception {
        if (id1.equals(id2)) {
            throw new ServiceException("AUTOCFG-009");
        }
        if (null == headId) {
            throw new ServiceException("AUTOCFG-010");
        }
        AutoCfgItem example = new AutoCfgItem();
        example.setId(id1);
        example.setCorpid(corp1);
        example.setLoginCorpId(corp1);


        example.setId(id2);
        example.setCorpid(corp2);
        example.setLoginCorpId(corp2);
        AutoCfgItem item1 = autoCfgItemMapper.queryById(example);
        AutoCfgItem item2 = autoCfgItemMapper.queryById(example);
        if (item1 != null && item2 != null) {
            Double seq1 = item1.getSeq();
            boolean equalFlag = false;
            if (seq1 != null) {
                if (item2.getSeq() != null && seq1.compareTo(item2.getSeq()) == 0) {
                    equalFlag = true;
                }
            } else if (item2.getSeq() == null) {
                equalFlag = true;
            }
            if (!equalFlag) {
                item1.setSeq(item2.getSeq());
                item2.setSeq(seq1);
                item1.setHeadId(headId);
                item2.setHeadId(headId);
                update(item1);
                update(item2);
            } else {
                System.out.println("Seq1 is Equal to Seq2");
            }
            Map<String, Object> result = new HashMap<String, Object>();
            result.put("item1", item1);
            result.put("item2", item2);
            return result;
        } else {
            System.err.println(id1 + ", " + id2 + ", " + corp1 + ", " + corp2);
            throw new ServiceException("AUTOCFG-011");
        }
    }

    @Transactional(rollbackFor = BasicServiceException.class)
    @Override
    public void upsertAndDel(List<AutoCfgItem> list) throws Exception {
        // TODO Auto-generated method stub
        for (AutoCfgItem item : list) {
            String op = item.getRow_status();
            switch (op) {
                case "UPDATE":
                    update(item);
                    //更新子元素，先删除再插入
                    if (item.getJoinSubFlag() != null
                            && item.getJoinSubFlag() == true
                            && item.getSubList() != null
                            && item.getSubList().size() > 0) {
                        AutoCfgItemSub subExample = new AutoCfgItemSub();
                        subExample.setParentId(item.getId());
                        autoCfgItemSubService.deleteByParentId(subExample);
                        for (AutoCfgItemSub sub : item.getSubList()) {
                            //sub.setId(null);
                            sub.setParentId(item.getId());
                            sub.setBasicStandardId(null);//再次更新的子元素，表示值已经过再次修改，将删除与母版的关联
                            autoCfgItemSubService.insert(sub);
                        }
                    }
                    break;

                case "NEW":
                    insert(item);
                    if (item.getJoinSubFlag() != null
                            && item.getJoinSubFlag() == true
                            && item.getSubList() != null
                            && item.getSubList().size() > 0) {
                        for (AutoCfgItemSub sub : item.getSubList()) {
                            sub.setParentId(item.getId());
                            autoCfgItemSubService.insert(sub);
                        }
                    }
                    break;

                case "DELETE":
                    deleteById(item);
                    //删除子元素
                    AutoCfgItemSub subExample = new AutoCfgItemSub();
                    subExample.setParentId(item.getId());
                    autoCfgItemSubService.deleteByParentId(subExample);
                    break;

                default:
                    break;
            }
        }
    }

    @Override
    public Map<String, Object> toCfgMap(AutoCfgItem record) {
        if (record == null) {
            return null;
        }
        Map<String, Object> result = new HashMap<String, Object>();
        // Field[] fs = record.getClass().getDeclaredFields();

        for (String stayField : record.stayFields) {
            try {
                Field field = record.getClass().getDeclaredField(stayField);
                field.setAccessible(true);
                Object obj = field.get(record);
                result.put(stayField, obj);
            } catch (NoSuchFieldException | SecurityException e) {
                // TODO Auto-generated catch block
                logger.error("AutoCfgItemServiceImpl捕获异常: ",e);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                // TODO Auto-generated catch block
                logger.error("AutoCfgItemServiceImpl捕获异常: ",e);
            }
        }
        if (record.getSubList() != null && record.getSubList().size() > 0) {
            for (AutoCfgItemSub sub : record.getSubList()) {
                result.put(sub.getName(), sub.getValue());
            }
        }
        return result;
    }
}
